package org.ciallo.simplemusicplayer.viewmodel;

import android.app.Application;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import org.ciallo.simplemusicplayer.data.model.Playlist;
import org.ciallo.simplemusicplayer.data.model.PlaylistInfo;
import org.ciallo.simplemusicplayer.data.model.Song;
import org.ciallo.simplemusicplayer.data.repository.PlaylistRepository;
import timber.log.Timber;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author Jukomu
 * @Description: 管理歌单相关逻辑的 ViewModel
 * @Package: org.ciallo.simplemusicplayer.viewmodel
 * @Project: SimpleMusicPlayer
 * @name: PlaylistViewModel
 * @Date: 2025/5/30-01:05
 * @Filename: PlaylistViewModel
 */
public class PlaylistViewModel extends AndroidViewModel {
    private final PlaylistRepository playlistRepository;

    private final MutableLiveData<String> currentPlaylistSearchQuery = new MutableLiveData<>();

    /**
     * LiveData，根据 currentPlaylistSearchQuery 的值，动态提供所有用户创建的歌单信息 (PlaylistInfo) 或过滤后的结果。
     * 不包含“我的收藏”这个特殊项。
     */
    public final LiveData<List<PlaylistInfo>> userPlaylistsToDisplay; // <--- 修改，只包含用户创建的


    // 用于通知UI歌单创建结果的 LiveData
    private final MutableLiveData<Long> _createdPlaylistId = new MutableLiveData<>();
    public final LiveData<Long> createdPlaylistId = _createdPlaylistId;

    // 用于通用加载状态和错误消息 (可以继承自一个 BaseViewModel)
    private final MutableLiveData<Boolean> _isLoading = new MutableLiveData<>(false);
    public final LiveData<Boolean> isLoading = _isLoading;

    private final MutableLiveData<String> _errorMessage = new MutableLiveData<>();
    public final LiveData<String> errorMessage = _errorMessage;


    public PlaylistViewModel(@NonNull Application application) {
        super(application);
        playlistRepository = new PlaylistRepository(application);
        // allPlaylistsWithInfo = playlistRepository.getAllPlaylistsWithInfo(); // 旧的

        currentPlaylistSearchQuery.setValue(""); // 初始为空搜索词

        userPlaylistsToDisplay = Transformations.switchMap(currentPlaylistSearchQuery, query -> {
            Timber.d("PlaylistViewModel: userPlaylistsToDisplay switchMap with query: '%s'", query);
            // 这个方法现在返回 LiveData<List<PlaylistInfo>>
            return playlistRepository.getPlaylistsInfoFilteredOrAll(query);
        });
    }

    public void updateSearchQuery(@Nullable String query) {
        String newQuery = (query != null) ? query.trim() : "";
        if (!Objects.equals(newQuery, currentPlaylistSearchQuery.getValue())) {
            currentPlaylistSearchQuery.setValue(newQuery);
        }
    }

    /**
     * 获取指定歌单及其包含的歌曲。
     * @param playlistId 歌单ID。
     * @return LiveData 包装的歌曲列表。
     */
    public LiveData<List<Song>> getSongsForPlaylist(long playlistId) {
        return playlistRepository.getSongsForPlaylistOrdered(playlistId);
    }

    /**
     * 获取指定歌单的详情。
     * @param playlistId 歌单ID。
     * @return LiveData 包装的歌单对象。
     */
    public LiveData<Playlist> getPlaylistDetails(long playlistId) {
        return playlistRepository.getPlaylistById(playlistId);
    }


    /**
     * 创建一个新的歌单。
     * @param name        歌单名称。
     * @param description 歌单描述 (可选)。
     */
    public void createPlaylist(String name, @Nullable String description) {
        _isLoading.postValue(true);
        // PlaylistRepository.createPlaylist 现在返回 Future<Long>
        Future<Long> creationFuture = playlistRepository.createPlaylist(name, description);

        // 处理 Future 的结果。在 ViewModel 中直接阻塞获取 Future 结果不是好主意。
        // 更好的方式是 Repository 直接返回 LiveData<Result> 或使用协程/RxJava。
        // 简单起见，这里我们可以在一个后台线程中获取 Future 的结果，然后更新 LiveData。
        // 或者让 Repository 内部处理异步并将结果 post 到一个 LiveData。
        // 为了演示，我们假设 Repository 的 createPlaylist 是异步的，并通过某种回调或 LiveData 返回结果。
        // 当前的 Repository.createPlaylist 返回 Future，我们需要异步等待它。

        // AppDatabase.databaseWriteExecutor 可用于此，但它用于数据库IO，
        // 等待 Future 不一定是最佳用途。我们可以用一个新的线程。
        new Thread(() -> {
            try {
                Long newId = creationFuture.get(); // 这会阻塞当前线程，直到 Future 完成
                _createdPlaylistId.postValue(newId);
                _isLoading.postValue(false);
                if (newId == null || newId <= 0) { // 假设0或负数为无效ID
                    _errorMessage.postValue("创建歌单失败 (返回ID无效)");
                }
            } catch (ExecutionException | InterruptedException e) {
                Timber.e(e, "Error waiting for playlist creation future.");
                _errorMessage.postValue("创建歌单时发生错误: " + e.getMessage());
                _isLoading.postValue(false);
                _createdPlaylistId.postValue(-1L); // 指示错误
            }
        }).start();
    }

    /**
     * 更新歌单信息。
     * @param playlist 要更新的歌单。
     */
    public void updatePlaylist(Playlist playlist) {
        playlistRepository.updatePlaylist(playlist);
        // 可以添加成功/失败的 LiveData 反馈
    }

    /**
     * 更新歌单信息。
     * @param playlist 要更新的歌单。
     */
    public void updatePlaylist(PlaylistInfo playlist) {
        playlistRepository.updatePlaylist(playlist);
        // 可以添加成功/失败的 LiveData 反馈
    }

    /**
     * 删除歌单。
     * @param playlist 要删除的歌单。
     */
    public void deletePlaylist(Playlist playlist) {
        playlistRepository.deletePlaylist(playlist);
        // 可以添加成功/失败的 LiveData 反馈
    }

    /**
     * 删除歌单。
     * @param playlist 要删除的歌单。
     */
    public void deletePlaylist(PlaylistInfo playlist) {
        playlistRepository.deletePlaylist(playlist);
        // 可以添加成功/失败的 LiveData 反馈
    }


    /**
     * 将歌曲添加到歌单。
     * @param playlistId 歌单ID。
     * @param songId     歌曲ID。
     */
    public void addSongToPlaylist(long playlistId, long songId) {
        // 可以在这里添加一些业务逻辑，例如检查歌曲是否已在歌单中（如果DAO支持）
        playlistRepository.addSongToPlaylist(playlistId, songId);
        // 通知UI更新（例如，歌单的歌曲数量），或者让UI观察相关的LiveData自动更新
    }

    /**
     * 从歌单中移除歌曲。
     * @param playlistId 歌单ID。
     * @param songId     歌曲ID。
     */
    public void removeSongFromPlaylist(long playlistId, long songId) {
        playlistRepository.removeSongFromPlaylist(playlistId, songId);
    }
}
